home *** CD-ROM | disk | FTP | other *** search
/ L' Effet Pommier 3 / L'Effet Pommier - Volume 03.iso / Graphismes / Bitmap / NIH Image 1.59 / Macros / Plotting Macros < prev    next >
Text File  |  1995-10-25  |  20KB  |  817 lines

  1. macro 'Plot Histogram';
  2. var
  3.   max,scale:real;
  4.   i,margin,width,height:integer;
  5. begin
  6.   SaveState;
  7.   Margin:=10;
  8.   width:=256;
  9.   height:=0.6*256;
  10.   Measure;
  11.   SetForegroundColor(255);
  12.   SetBackgroundColor(0);
  13.   SetLineWidth(1);
  14.   SetNewSize(width+2*margin,height+2*margin);
  15.   MakeNewWindow('Histogram');
  16.   MakeRoi(margin,margin-1,width,height+1);
  17.   DrawBoundary;
  18.   max:=0;
  19.   for i:=1 to 254 do
  20.   if histogram[i]> max then max:=histogram[i];
  21.   scale:=height/max;
  22.   for i:=1 to 254 do begin
  23.     MakeRoi(margin+i,margin,1,histogram[i]*scale);
  24.     SetForegroundColor(i);
  25.     fill;
  26.  end;
  27.   SelectAll;
  28.   FlipVertical;
  29.   KillRoi;
  30.   RestoreState;
  31. end;
  32.  
  33. macro 'Stack Histogram';
  34. var
  35.   max,scale:real;
  36.   i,margin,width,height:integer;
  37. begin
  38.   SaveState;
  39.   Margin:=10;
  40.   width:=256;
  41.   height:=0.6*256;
  42.   Measure;
  43.   SetForegroundColor(255);
  44.   SetBackgroundColor(0);
  45.   SetLineWidth(1);
  46.   SetNewSize(width+2*margin,height+2*margin);
  47.   MakeNewWindow('Histogram');
  48.   MakeRoi(margin,margin-1,width,height+1);
  49.   DrawBoundary;
  50.   max:=0;
  51.   for i:=1 to 254 do
  52.   if histogram[i]> max then max:=histogram[i];
  53.   scale:=height/max;
  54.   for i:=1 to 254 do begin
  55.     MakeRoi(margin+i,margin,1,histogram[i]*scale);
  56.     SetForegroundColor(i);
  57.     fill;
  58.  end;
  59.   SelectAll;
  60.   FlipVertical;
  61.   KillRoi;
  62.   RestoreState;
  63. end;
  64.  
  65. procedure DoColumnPlot(MaxCount: integer);
  66. {Plots the User1 column in the Results table.}
  67. var
  68.    xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  69.    width,height,margin,pwidth,pheight:integer;
  70.    y,pbottom, barWidth, barLeft, barTop:integer;
  71.    sum:integer;
  72. begin
  73.   SaveState;
  74.   margin:=40;
  75.   width:=500;
  76.   height:=300;
  77.   sum:=0;
  78.   ymin:=0;
  79.   ymax:=-999999;
  80.   for i:=1 to maxCount do
  81.       if rUser1[i]>ymax then ymax:=rUser1[i];
  82.   xmin:=1;
  83.   xmax:=maxCount;
  84.   SetNewSize(width,height);
  85.   SetForeground(255);
  86.   SetBackground(0);
  87.   MakeNewWindow('Histogram');
  88.   pwidth:=width-2*margin;
  89.   pheight:=height-2*margin;
  90.   pbottom:=margin+pheight;
  91.   xscale:=pwidth/xmax;
  92.   yscale:=pheight/(ymax-ymin);
  93.   barWidth:=round(pwidth/maxCount)+1;
  94.   SetForeground(255);
  95.   SetBackground(0); 
  96.   SetLineWidth(1);
  97.   for i:=0 to maxCount-1 do begin
  98.      barLeft:=margin+i*xscale;
  99.      barTop:=pbottom-(rUser1[i+1]-ymin)*yscale;
  100.      MakeRoi(barLeft, barTop, barWidth, pBottom-barTop);
  101.      fill;
  102.      sum:=sum+(i+1)*rUser1[i+1];
  103.   end;
  104.   KillRoi;
  105.   MoveTo(margin,margin);
  106.   LineTo(margin,margin+pheight);
  107.   SetFont('Geneva');
  108.   SetFontSize(9);
  109.   SetText('Centered');
  110.   MoveTo(margin+4,margin+pheight+12);
  111.   writeln(xmin:1:2);
  112.   MoveTo(margin+pwidth,margin+pheight+12);
  113.   writeln(xmax:1:2);
  114.   SetText('Right Justified');
  115.   MoveTo(margin-2,margin+pheight-5);
  116.   writeln(ymin:1:2);
  117.   MoveTo(margin-2,margin);
  118.   writeln(ymax:1:2);
  119.   MoveTo(margin+pwidth/2-15, margin+pheight+12);
  120.   RestoreState;
  121.   ShowMessage('sum=',sum:1,'\ymax=',ymax:1);
  122. end;
  123.  
  124.  
  125. macro 'Plot Histogram Using Bins';
  126. var
  127.   i, nBins, bin: integer;
  128.   ValuesPerBin, TotalArea: real;
  129.    n, lower, upper, nValues: integer;
  130.    first, last: integer;
  131. begin
  132.   ResetCounter;
  133.   nBins:=GetNumber('Number of Bins (1-256)', 10);
  134.   SetUser1Label('%');
  135.   SetUser2Label('Area');
  136.   Measure;
  137.   TotalArea := rArea[rCount];
  138.   GetThreshold(lower, upper);
  139.   if (lower = 0) and (upper = 0) then
  140.      upper := 255;
  141.   nValues := upper - lower + 1;
  142.   n := 0;
  143.   for i := lower to upper do
  144.      n := n + histogram[i];
  145.   ValuesPerBin := nValues / nBins;
  146.   for bin := 1 to nBins do
  147.       rUser1[bin] := 0;
  148.   {for i := lower to upper do begin
  149.       bin := trunc((i - lower) / ValuesPerBin) + 1;
  150.       rUser1[bin] := rUser1[bin] + Histogram[i];
  151.   end;}
  152.   SaveState;
  153.   SetFont('Monaco');
  154.   SetFontSize(9);
  155.   NewTextWindow('Histogram Data', 280, 450);
  156.   writeln(' Bin    Range   Count   Percent   Area');
  157.   for bin := 1 to nBins do begin
  158.       first := lower + trunc((nValues * (bin - 1)) / nBins);
  159.       last := lower + trunc((nValues * bin) / nBins) -1 ;
  160.       for i := first to last do
  161.          rUser1[bin] := rUser1[bin] + Histogram[i];
  162.       writeln(bin:3, first:6, last:4, rUser1[bin]:8, (rUser1[bin] / n) * 100:8:2, TotalArea * rUser1[bin] / n:10:2);
  163.   end;
  164.   RestoreState;
  165.   for bin := 1 to nBins do
  166.       rUser1[bin] :=  (rUser1[bin] / n) * 100.0;
  167.   for bin := 1 to nBins do
  168.       rUser2[bin] :=  TotalArea * rUser1[bin] / 100;
  169.   SetCounter(nBins);
  170.   DoColumnPlot(nBins);
  171. end;
  172.  
  173.  
  174. procedure DrawPerimeter;
  175. var
  176.   length1, length2: integer;
  177.   dx1, dx2, dy1, dy2: integer;
  178.   dxp1, dxp2, dyp1, dyp2: integer;
  179.   sumdx, sumdy, corners: integer;
  180.   corner: boolean;
  181.   perimeter: real;
  182. begin
  183.   RedLUT[254] := 255;
  184.   GreenLUT[254] := 0;
  185.   BlueLUT[254] := 0;
  186.   SetForeground(254);
  187.   sumdx := 0.0;
  188.   sumdy := 0.0;
  189.   corners := 0;
  190.   dx1 := xCoordinates[1] - xCoordinates[nCoordinates];
  191.   dy1 := yCoordinates[1] - yCoordinates[nCoordinates];
  192.   length1 := abs(dx1) + abs(dy1);
  193.   dxp1 := dx1;
  194.   if dxp1 > 1 then dxp1 := 1;
  195.   if dxp1 < -1 then dxp1 := -1;
  196.   dyp1 := dy1;
  197.   if dyp1 > 1 then dyp1 := 1;
  198.   if dyp1 < -1 then dyp1 := -1;
  199.   corner := false;
  200.   for i := 1 to nCoordinates do begin
  201.      dx2 := xCoordinates[i+1] - xCoordinates[i];
  202.      dy2 := yCoordinates[i+1] - yCoordinates[i];
  203. {showmessage(i, abs(dx1), abs(dy1)); wait(2);}
  204.      sumdx := sumdx + abs(dx1);
  205.      sumdy := sumdy + abs(dy1);
  206.      length2 := abs(dx2) + abs(dy2);
  207.      dxp2 := dx2;
  208.      if dxp2 > 1 then dxp2 := 1;
  209.      if dxp2 < -1 then dxp2 := -1;
  210.      dyp2 := dy2;
  211.      if dyp2 > 1 then dyp2 := 1;
  212.      if dyp2 < -1 then dyp2 := -1;
  213.      if (length1 > 1) or (not corner) then begin
  214.         MoveTo((xCoordinates[i]-dxp1)*scale+10, (yCoordinates[i]-dyp1)*scale+10);
  215.         LineTo((xCoordinates[i]+dxp2)*scale+10, (yCoordinates[i]+dyp2)*scale+10);
  216.         corner := true;
  217.         corners := corners + 1;
  218.      end else
  219.         corner := false;
  220.      dx1 := dx2;
  221.      dy1 := dy2;
  222.      dxp1 := dxp2;
  223.      dyp1 := dyp2;
  224.      length1 := length2;
  225.   end;
  226.   perimeter := sumdx + sumdy;
  227. end;
  228.  
  229. procedure ShowPerimeter;
  230. var
  231.   length1, length2: integer;
  232.   dx1, dx2, dy1, dy2: integer;
  233.   sumdx, sumdy, nCorners: integer;
  234.   corner: boolean;
  235.   perimeter: real;
  236. begin
  237.   sumdx := 0.0;
  238.   sumdy := 0.0;
  239.   nCorners := 0;
  240.   dx1 := xCoordinates[1] - xCoordinates[nCoordinates];
  241.   dy1 := yCoordinates[1] - yCoordinates[nCoordinates];
  242.   length1 := abs(dx1) + abs(dy1);
  243.   corner := false;
  244.   for i := 1 to nCoordinates do begin
  245.      dx2 := xCoordinates[i+1] - xCoordinates[i];
  246.      dy2 := yCoordinates[i+1] - yCoordinates[i];
  247.      sumdx := sumdx + abs(dx1);
  248.      sumdy := sumdy + abs(dy1);
  249.      length2 := abs(dx2) + abs(dy2);
  250.      if (length1 > 1) or (not corner) then begin
  251.         corner := true;
  252.         nCorners := nCorners + 1;
  253.      end else
  254.         corner := false;
  255.      dx1 := dx2;
  256.      dy1 := dy2;
  257.      length1 := length2;
  258.   end;
  259.   perimeter := sumdx + sumdy;
  260.   MoveTo(width/3,height/3 + 40);
  261.   Writeln('perimeter1=', perimeter:1:2);
  262.   Writeln('perimeter2=', perimeter - nCorners * (2 - sqrt(2)):1:2);
  263.   Writeln('perimeter3=', perimeter*0.948 - nCorners * (2 - 1.34):1:2);
  264. end;
  265.  
  266. procedure DrawX(x, y:integer);
  267. begin
  268.   moveto(x+3, y+3);
  269.   lineto(x-3, y-3);
  270.   moveto(x+3, y-3);
  271.   lineto(x-3, y+3);
  272.   lineto(x, y);
  273. end;
  274.  
  275.  
  276. macro 'Plot XY Coordinates [X]';
  277. {Plots the X-Y Coordinates of the current ROI.}
  278. var
  279.   i,w,h,width,height:integer;
  280.   xbase,ybase,RoiWidth,RoiHeight:integer
  281.   x,y,scale,xmax,ymax:real 
  282. begin
  283.   RequiresVersion(1.48);
  284.   if nCoordinates=0 then begin
  285.     beep;
  286.     PutMessage('No X-Y Coordinates available.');
  287.     exit;
  288.   end;
  289.   GetRoi(xbase,ybase,RoiWidth,RoiHeight);
  290.   SaveState;
  291.   InvertY(false);
  292.   xmax:=0;
  293.   ymax:=0;
  294.   for i:=1 to nCoordinates do begin
  295.     x:=xCoordinates[i];
  296.     y:=yCoordinates[i];
  297.     if x>xmax then xmax:=x;
  298.     if y>ymax then ymax:=y;
  299.   end;
  300.   scale:=sqrt((300*300)/(xmax*ymax));
  301.   if (xmax*scale)>500 then scale:=500/xmax;
  302.   if (ymax*scale)>500 then scale:=500/ymax;
  303.   SetForegroundColor(255);
  304.   SetBackgroundColor(0);
  305.   SetNewSize(xmax*scale+20,ymax*scale+20);
  306.   MakeNewWindow('Outline');
  307.   MoveTo(xCoordinates[1]*scale+10,yCoordinates[1]*scale+10);
  308.   for i:=2 to nCoordinates do begin
  309.     LineTo(xCoordinates[i]*scale+10,yCoordinates[i]*scale+10);
  310.     if nCoordinates < 100 then
  311.        DrawX(xCoordinates[i]*scale+10,yCoordinates[i]*scale+10);
  312.   end;
  313.   SetFont('Helvetica');
  314.   SetFontSize(12);
  315.   SetText('No background, Left Justified');
  316.   GetPicSize(width,height);
  317.   MoveTo(width/3,height/3);
  318.   Writeln(nCoordinates:1,' coordinate pairs');
  319.   Writeln('Origin=',xbase:1,', ',ybase:1);
  320.   Writeln('xmax=',xmax:1, ', ymax=',ymax:1,);
  321.   {DrawPerimeter;}
  322.   {ShowPerimeter;}
  323.   RestoreState;
  324. end;
  325.  
  326.  
  327. procedure PlotProfile2(integrate:boolean);
  328. var
  329.   xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  330.   width,height,margin,pwidth,pheight:integer;
  331.   count:integer;
  332.   ppv:integer; {Pixels per Value}
  333. begin
  334.   SaveState;
  335.   margin:=40;
  336.   width:=500;
  337.   height:=300;
  338.   GetPlotData(count,ppv,ymin,ymax);
  339.   if count=0 then begin
  340.     PutMessage('No plot data available.');
  341.     exit;
  342.   end;
  343.   if integrate then begin
  344.      ymin:=ymin*ppv;
  345.      ymax:=ymax*ppv;
  346.   end;
  347.   xmin:=0;
  348.   xmax:=count-1;
  349.   SetNewSize(width,height);
  350.   SetForeground(255);
  351.   SetBackground(0);
  352.   MakeNewWindow('Plot');
  353.   pwidth:=width-2*margin;
  354.   pheight:=height-2*margin;
  355.   xscale:=pwidth/(xmax-xmin);
  356.   yscale:=pheight/(ymax-ymin);
  357.   SetForeground(255);
  358.   SetBackground(0); 
  359.   SetLineWidth(1); 
  360.   MoveTo(margin,margin);
  361.   if integrate then for i:=0 to count-1 do
  362.        LineTo(margin+i*xscale,margin+(PlotData[i]*ppv-ymin)*yscale)
  363.   else  for i:=0 to count-1 do
  364.         LineTo(margin+i*xscale,margin+(PlotData[i]-ymin)*yscale);
  365.   MakeRoi(margin,margin,pwidth+1,pheight+2);
  366.   MoveTo(margin,margin);
  367.   LineTo(margin+pwidth,margin);
  368.   MoveTo(margin,margin);
  369.   LineTo(margin,margin+pheight);
  370.   FlipVertical;
  371.   KillRoi;
  372.   SetFont('Geneva');
  373.   SetFontSize(9);
  374.   SetText('Centered');
  375.   MoveTo(margin+4,margin+pheight+12);
  376.   writeln(xmin:1:2);
  377.   MoveTo(margin+pwidth,margin+pheight+12);
  378.   writeln(xmax:1:2);
  379.   SetText('Right Justified');
  380.   MoveTo(margin-2,margin+pheight-5);
  381.   writeln(ymin:1:2);
  382.   MoveTo(margin-2,margin);
  383.   writeln(ymax:1:2);
  384.   RestoreState;
  385. end;
  386.  
  387.  
  388. macro 'Plot Profile';
  389. begin
  390.   PlotProfile2(false);
  391. end;
  392.  
  393. macro 'Plot Integrated Profile';
  394. begin
  395.   PlotProfile2(true);
  396. end;
  397.  
  398. macro 'Plot Radial Profiles╔ [R]';
  399. var
  400.   x1,y1,x2,y2,pi,angle,delta:real;
  401.   LineWidth,i,nLines,radius,PlotWidth,PlotHeight:integer;
  402.   MinPlotWidth,hMargin,vMargin,PlotLeft,PlotTop:integer;
  403.   LeftMargin,RightMargin,TopMargin,BottomMargin:integer;
  404.   ImageWindow,PlotWindow:integer;
  405.   nPixels,mean,mode,min,max:real;
  406. begin
  407.   RequiresVersion(1.54);
  408.   SaveState;
  409.   GetLine(x1,y1,x2,y2,LineWidth);
  410.   if x1<0 then begin
  411.     PutMessage('Please select a point by clicking with the line tool.');
  412.     exit;
  413.   end;
  414.   radius:=GetNumber('Radius:',20);
  415.   nLines:=GetNumber('Number of Lines:',8);
  416.   MinPlotWidth:=140;
  417.   pi:=3.14159;
  418.   delta:=2.0*pi/nLines;
  419.   angle:=0.0;
  420.   PlotWidth:=radius;
  421.   if PlotWidth<MinPlotWidth then PlotWidth:=MinPlotWidth;
  422.   PlotHeight:=0.4*PlotWidth;
  423.   SetPlotSize(PlotWidth,PlotHeight);
  424.   MakeOvalRoi(x1-radius,y1-radius,radius*2,radius*2);
  425.   Measure;
  426.   GetResults(nPixels,mean,mode,min,max);
  427.   min:=min-10;
  428.   if min<0 then min:=0;
  429.   max:=max+10;
  430.   if max>255 then max:=255;
  431.   SetPlotScale(cValue(min),cValue(max));
  432.   SetPlotLabels(false);
  433.   hMargin:=5;
  434.   vMargin:=5;
  435.   LeftMargin:=38;
  436.   TopMargin:=10;
  437.   RightMargin:=20;
  438.   BottomMargin:=20;
  439.   PlotLeft:=hMargin-LeftMargin;
  440.   PlotTop:=vMargin-TopMargin;
  441.   SetNewSize(PlotWidth+2*hMargin,PlotHeight*nLines);
  442.   SetForegroundColor(255);
  443.   SetBackgroundColor(0);
  444.   ImageWindow:=PicNumber;
  445.   MakeNewWindow('Plots');
  446.   PlotWindow:=PicNumber;
  447.   SelectPic(ImageWindow);
  448.   for i:=1 TO nLines do begin
  449.     x2:=x1+round(radius*cos(angle));
  450.     y2:=y1+round(radius*sin(angle));
  451.     MakeLineRoi(x1,y1,x2,y2);
  452.     PlotProfile;
  453.     Copy;
  454.     SelectPic(PlotWindow);
  455.     MakeRoi(PlotLeft,PlotTop,PlotWidth+LeftMargin+RightMargin,
  456.           PlotHeight+TopMargin+BottomMargin);
  457.     Paste;
  458.     DoOr;
  459.     PlotTop:=PlotTop+PlotHeight-1;
  460.     SelectPic(ImageWindow);
  461.     angle:=angle+delta;
  462.   end;
  463.   RestoreState;
  464. end;
  465.  
  466.  
  467. macro 'Radial Intensity Distibution╔';
  468. var
  469.   x1,y1,x2,y2,pi,angle,delta:real;
  470.   radius,ymin,ymax,sum:real;
  471.   i,j,LineWidth,nLines,count,ppv:integer;
  472. begin
  473.   RequiresVersion(1.54);
  474.   SaveState;
  475.   GetLine(x1,y1,x2,y2,LineWidth);
  476.   if x1<0 then begin
  477.     PutMessage('Please select a point by clicking with the line tool.');
  478.     exit;
  479.   end;
  480.   radius:=GetNumber('Radius (pixels):',50);
  481.   nLines:=GetNumber('Number of Lines:',25);
  482.   for i:= 1 to radius do rUser1[i]:=0;
  483.   pi:=3.14159;
  484.   delta:=2.0*pi/nLines;
  485.   angle:=0.0;
  486.   for i:=1 to nLines do begin
  487.     x2:=x1+round(radius*cos(angle));
  488.     y2:=y1+round(radius*sin(angle));
  489.     MakeLineRoi(x1,y1,x2,y2);
  490.     GetPlotData(count,ppv,ymin,ymax);
  491.     for j:=1 to count do
  492.         rUser1[j]:=rUser1[j]+PlotData[j];
  493.     angle:=angle+delta;
  494.   end;
  495.   RestoreState;
  496.   DoColumnPlot(radius);
  497. end;
  498.  
  499.  
  500. macro 'Circular Profile Plot [C]';
  501. var
  502.   radius,pi,angle,dx,dy,delta:real;
  503.   x1,y1,x2,y2:real;
  504.   npoints,i,value,LineWidth,x,y,px:integer;
  505. begin
  506.   GetLine(x1,y1,x2,y2,LineWidth);
  507.   if x1< 0 then begin
  508.     PutMessage('Please select a point by clicking with the line tool.');
  509.     exit;
  510.   end;
  511.   x:=x1+(x2-x1)/2;
  512.   y:=y1+(y2-y1)/2;
  513.   radius:=sqrt(sqr(x2-x1)+sqr(y2-y1))/2;
  514.   if radius<3 then begin
  515.     PutMessage('The line selection must be longer than 5 pixels.');
  516.     exit;
  517.   end;
  518.   npoints:=radius*2;
  519.   pi:=3.14159;
  520.   delta:=2.0*pi/npoints;
  521.   angle:=0.0;
  522.   px:=0;
  523.   for i:=1 TO npoints do begin
  524.     dx:=round(radius*cos(angle));
  525.     dy:=round(radius*sin(angle));
  526.     value:=GetPixel(x+dx,y+dy);
  527.     PutPixel(x+dx,y+dy,255);
  528.     PutPixel(px,0,value);
  529.     px:=px+1;
  530.     angle:=angle+delta;
  531.   end;
  532.   MakeLineRoi(0,0,npoints,0);
  533.   PlotProfile;
  534.   KillRoi;
  535. end;
  536.  
  537. macro 'Export Profile Plots╔';
  538. var
  539.   y,yInc,width,height,n:integer;
  540. begin
  541.   yInc:=GetNumber('Y Increment:',10);
  542.   GetPicSize(width,height);
  543.   y:=0;
  544.   n:=0;
  545.   SetExport('Plot Values');
  546.   repeat
  547.     MakeLineRoi(0,y,width-1,y);
  548.     PlotProfile;
  549.     Export('PLOT',n:4);
  550.     n:=n+1;
  551.     y:=y+yInc;
  552.   until y>=height;
  553. end;
  554.  
  555.  
  556. procedure PlotMeans;
  557. {Plots the mean column in the Results table.}
  558. var
  559.    xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  560.   width,height,margin,pwidth,pheight:integer;
  561.   y,pbottom:integer;
  562. begin
  563.   margin:=40;
  564.   width:=500;
  565.   height:=300;
  566.   ymax:=-999999;
  567.   ymin:=999999;
  568.   for i:=1 to rCount do begin
  569.     y:=rMean[i];
  570.     if y>ymax then ymax:=y;
  571.     if y<ymin then ymin:=y;
  572.   end;
  573.   xmin:=0;
  574.   xmax:=rCount-1;
  575.   SetNewSize(width,height);
  576.   SetForeground(255);
  577.   SetBackground(0);
  578.   MakeNewWindow('Z-Axis Profile Plot');
  579.   pwidth:=width-2*margin;
  580.   pheight:=height-2*margin;
  581.   pbottom:=margin+pheight;
  582.   xscale:=pwidth/(xmax-xmin);
  583.   yscale:=pheight/(ymax-ymin);
  584.   SetForeground(255);
  585.   SetBackground(0); 
  586.   SetLineWidth(1);
  587.   MoveTo(margin,pbottom-(rMean[1]-ymin)*yscale);
  588.   for i:=2 to rCount do
  589.      LineTo(margin+(i-1)*xscale,pbottom-(rMean[i]-ymin)*yscale);
  590.   MoveTo(margin,pbottom);
  591.   LineTo(margin+pwidth,pbottom);
  592.   MoveTo(margin,margin);
  593.   LineTo(margin,margin+pheight);
  594.   SetFont('Geneva');
  595.   SetFontSize(9);
  596.   SetText('Centered');
  597.   MoveTo(margin+4,margin+pheight+12);
  598.   writeln(xmin:1:2);
  599.   MoveTo(margin+pwidth,margin+pheight+12);
  600.   writeln(xmax:1:2);
  601.   SetText('Right Justified');
  602.   MoveTo(margin-2,margin+pheight-5);
  603.   writeln(ymin:1:2);
  604.   MoveTo(margin-2,margin);
  605.   writeln(ymax:1:2);
  606. end;
  607.  
  608. macro 'Plot Z-Axis Profile [Z]';
  609. {Plots the average density of an roi through a stack.}
  610. var
  611.   left,top,width,height,i:integer;
  612. begin
  613.   if (nPics=0) or (nSlices=0) then begin
  614.      PutMessage('This macro requires a stack.');
  615.      exit;
  616.   end;
  617.   GetRoi(left,top,width,height);
  618.   if width=0 then begin
  619.      PutMessage('Selection required.');
  620.      exit;
  621.   end;
  622.   ResetCounter;
  623.   {SetOptions('Mean');}
  624.   for i:= 1 to nSlices do begin
  625.      SelectSlice(i);
  626.      Measure;
  627.   end;
  628.   PlotMeans;
  629.  end;
  630.  
  631.  
  632. macro 'Plot XYZ';
  633. {
  634. Plots X-Y coordinate points with an optional intensity(Z). Values are read from
  635. a 2 or 3 column tab-delimited text file. Data must be scaled as follows:
  636. 0<=X<width; 0<=Y<height; 0<=Z<=255.
  637. }
  638. var
  639.   width,height:integer;
  640. begin
  641.   SaveState;
  642.   width:=500;
  643.   height:=500;
  644.   SetNewSize(width,height);
  645.   SetForeground(255);
  646.   SetBackground(0);
  647.   MakeNewWindow('Plot');
  648.   PlotXYZ;
  649.   RestoreState;
  650. end;
  651.  
  652. macro 'Draw Fitted Ellipse in White';
  653. var
  654.   left,top,width,height:real;
  655. begin
  656.   GetRoi(left,top,width,height);
  657.   if width=0 then begin
  658.     PutMessage('This macro requires a selection.');
  659.     exit;
  660.   end;
  661.   SetOptions('Area; Mean; X-Y Center');
  662.   Measure;
  663.   SetOption; MarkSelection;
  664.   KillRoi;
  665.   SelectAll;
  666.   KillRoi;
  667.  end;
  668.  
  669. macro 'Draw Calibration Bar [B]';
  670. {Generates a vertical calibration bar with labels.}
  671. var
  672.   top,left,width,height,nLabels,i:integer;
  673.   vloc,fwidth,digits,value:integer;
  674. begin
  675.   SaveState;
  676.   GetRoi(left,top,width,height);
  677.   if width=0 then begin
  678.     PutMessage('This macro requires a selection.');
  679.     exit;
  680.   end;
  681.   if width>height then begin
  682.     PutMessage('Selection must be vertically oriented.');
  683.     exit;
  684.   end;
  685.   nLabels:=round(height/25);
  686.   if nLabels<2 then nLabels:=2;
  687.   SetFontSize(9);
  688.   SetFont('Monaco');
  689.   SetText('Left Justified, With Background');
  690.   DrawScale;
  691.   {FlipVertical;}
  692.   KillRoi;
  693.   SetForeground(255); {black}
  694.   SetBackground(0); {white}
  695.   if calibrated then begin
  696.      fwidth:=7;
  697.     digits:=4;
  698.   end else begin
  699.     fwidth:=3;
  700.     digits:=0;
  701.   end;
  702.   vloc:=top;
  703.   for i:=0 to nLabels-1 do begin
  704.     vloc:=top+round(i*((height-1)/(nLabels-1)));
  705.     if vloc>=(top+height) then vloc:=top+height-1;
  706.     MoveTo(left+width+4,vloc+3);
  707.     value:=cvalue(GetPixel(left,vloc));
  708.     Write(value:fwidth:digits);
  709.     vloc:=vloc+round(height/(nLabels-1));
  710.   end;
  711.   RestoreRoi;
  712.   SetForeground(0); {white}
  713.   InsetRoi(-1);
  714.   DrawBoundary;
  715.   KillRoi;
  716.   RestoreState;
  717. end;
  718.  
  719.  
  720. macro 'Show Polar Coordiates [P]';
  721. {Returns polar coordinates of a point selected with the mouse, using centre 
  722. of the image as 0,0.  Data are displayed in the Info window as distance from 
  723. centre of image, and angle in degrees measured clockwise, where 0 is the 
  724. 12 o'clock position}
  725. var
  726.     Wide, High,x2,y2:integer;
  727.     x1,y1,D,Theta,rad:real;
  728. begin
  729.    rad:=180/3.14159265;
  730.    InvertY(true);
  731.    GetPicSize(Wide,High);
  732.    SetCursor('cross');
  733.    repeat
  734.       GetMouse(x2,y2);
  735.       x1:=Wide/2;
  736.       y1:=High/2;
  737.       y2:=High-y2
  738.       if (x1=x2) and (y1=y2) then begin
  739.          D:=0;
  740.          Theta:=0;
  741.       end;
  742.       if (y1<>y2) then begin
  743.          D:= sqrt((sqr(x2-x1))+ (sqr(y2-y1)));
  744.          Theta:=rad*(arctan((x2-x1)/(y2-y1)));
  745.       end;
  746.       if (y2<y1) then begin
  747.          Theta:=180 + Theta; 
  748.       end;
  749.       if (x2<x1) and (y2>y1) then begin
  750.          Theta:=360+Theta;
  751.       end;
  752.       ShowMessage('Distance: ',D:5:1'\''Angle: ',Theta:5:1); 
  753.       Wait(0.2);
  754.    until button;
  755. end;
  756.  
  757.  
  758. macro 'Record XY [X]';
  759. {Records the X-Y Coordinates of each pixel in the perimeter
  760. of a particle (selected with the wand) and saves the data to a
  761. comma-delimited text file}
  762. var
  763.     i,w,h:real;
  764.    xbase,ybase,width,height,RoiWidth,RoiHeight:real
  765.    x,y,xmax,ymax:real 
  766. begin
  767.    GetPicSize(width,height);
  768.    GetRoi(xbase,ybase,RoiWidth,RoiHeight);
  769.     if (RoiWidth=0) or (nCoordinates=0) then begin
  770.       PutMessage('Select a particle with the wand.');
  771.        exit;
  772.    end;
  773.   InvertY(false);
  774.    NewTextWindow('XY Data',150,400);
  775.    for i:=1 to nCoordinates do
  776.       Writeln(i,',',xCoordinates[i]+xbase:5:0,',',Height-yCoordinates[i]-ybase:5:0);
  777. end;
  778.  
  779.  
  780. procedure WriteReal(r:real);
  781. {Writes a real number using scientific notation.}
  782. var
  783.   e: integer;
  784. begin
  785.   e := 0;
  786.   while r >= 10 do begin
  787.     r := r / 10;
  788.     e := e + 1;
  789.   end;
  790.   while r < 1 do begin
  791.     r := r * 10;
  792.     e := e - 1;
  793.   end;
  794.   write(r:8:6);
  795.   if e >= 0 then
  796.                 write('e+')
  797.   else begin
  798.     e := -e;
  799.                 write('e-')
  800.   end;
  801.   if e <10 then
  802.      write('0');
  803.   write(e:1);
  804. end;
  805.  
  806.  
  807. macro 'Write Real Test...';
  808. var
  809.   r: real;
  810. begin
  811.   r := GetNumber('Enter a real number:', 1.234);
  812.   NewTextWindow('Output');
  813.   WriteReal(r);
  814. end;
  815.  
  816.  
  817.